using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;

namespace LuaNetInterface
{
    /// <summary>
    /// This class is a descriptor of a Lua package, containing information about the package
    /// and the functions and packages it contains.
    /// </summary>
    public class LuaPackageDescriptor
    {
        #region Data Members
        /// <summary>
        /// The name of the package.
        /// </summary>
        public string _name;

        /// <summary>
        /// The documentation attached to the package.
        /// </summary>
        public string _documentation;

        /// <summary>
        /// The functions contained within this package.
        /// </summary>
        public Hashtable _functions;

        /// <summary>
        /// The package contained within this package.
        /// </summary>
        public Hashtable _packages;
        #endregion

        #region Properties
        /// <summary>
        /// Gets the name of the package.
        /// </summary>
        public string Name
        {
            get { return _name; }
        }

        /// <summary>
        /// Gets the documentation attached to the package.
        /// </summary>
        public string Documentation
        {
            get { return _documentation; }
        }

        /// <summary>
        /// Gets the functions contained within this package.
        /// </summary>
        public Hashtable Functions
        {
            get { return _functions; }
        }
        #endregion

        #region Methods
        /// <summary>
        /// Creates the Lua package descriptor.
        /// </summary>
        /// <param name="name">The name of the package.</param>
        /// <param name="documentation">The documentation attached to the package.</param>
        public LuaPackageDescriptor(string name, string documentation)
        {
            _name = name;
            _documentation = documentation;

            if (_packages == null)
                _packages = new Hashtable();

            if (_functions == null)
                _functions = new Hashtable();
        }

        /// <summary>
        /// Adds a function to the Lua package.
        /// </summary>
        /// <param name="function">The function to add to the package.</param>
        public void AddFunction(LuaFunctionDescriptor function)
        {
            _functions.Add(function.Name, function);
        }

        /// <summary>
        /// Adds a sub-package to this Lua package.
        /// </summary>
        /// <param name="package">The sub-package to add to this package.</param>
        public void AddPackage(LuaPackageDescriptor package)
        {
            _packages.Add(package.Name, package);
        }

        /// <summary>
        /// Displays help for this package.
        /// </summary>
        public void ShowHelp()
        {
            IDictionaryEnumerator functions = _functions.GetEnumerator();
            IDictionaryEnumerator packages = _packages.GetEnumerator();

            // Display the information about the sub-packages contained within this package
            if (_packages.Count > 0)
            {
                Console.WriteLine("Available packages within " + _name + ": ");
                Console.WriteLine();

                while (packages.MoveNext())
                {
                    Console.WriteLine(((LuaPackageDescriptor)packages.Value).Name);
                }

                Console.WriteLine();
            }
            else
            {
                Console.WriteLine("No nested packages within " + _name);
                Console.WriteLine();
            }

            // Display the information about the functions contained within the package
            if (_functions.Count > 0)
            {
                Console.WriteLine("Available functions within " + _name + ": ");
                Console.WriteLine();

                while (functions.MoveNext())
                {
                    Console.WriteLine(((LuaFunctionDescriptor)functions.Value).GetFunctionHeader());
                }
            }
            else
            {
                Console.WriteLine("No nested functions within " + _name);
                Console.WriteLine();
            }
        }

        /// <summary>
        /// Displays in-depth help for a specific function or sub-package within this package.
        /// </summary>
        /// <param name="command">The name of the function or sub-package.</param>
        /// <returns>The help documentation string for the function or sub-package.</returns>
        public string ShowHelp(string command)
        {
            string result = "";
            LuaFunctionDescriptor function = (LuaFunctionDescriptor)_functions[command];
            LuaPackageDescriptor package = (LuaPackageDescriptor) _packages[command];

            if (function != null)
                result += function.FullDocumentationString + "\n";
            else if (package != null)
                result += package.Documentation + "\n";
            else
                result += "Item " + command + " does not exist in this package" + "\n";

            result += "\n";

            return result;
        }

        /// <summary>
        /// Checks if the package contains the function with the specified name.
        /// </summary>
        /// <param name="function">The name of the function to search for.</param>
        /// <returns>Whether or not the package contains the function.</returns>
        public bool HasFunction(string function)
        {
            return _functions.ContainsKey(function);
        }

        /// <summary>
        /// Checks if the package contains the sub-package with the specified name.
        /// </summary>
        /// <param name="package">The name of the sub-package to search for.</param>
        /// <returns>Whether or not the package contains the sub-package.</returns>
        public bool HasPackage(string package)
        {
            return _packages.ContainsKey(package);
        }

        /// <summary>
        /// Gets the documentation header for the Lua package.
        /// </summary>
        /// <returns>The documentation header for the package.</returns>
        public string GetPackageHeader()
        {
            if (_documentation.IndexOf("\n") == -1)
                return _documentation;

            return _documentation.Substring(0, _documentation.IndexOf("\n"));
        }
        #endregion
    }
}
